package com.iteaj.iot.server;

import com.iteaj.iot.*;
import com.iteaj.iot.server.manager.DevicePipelineManager;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;

/**
 * 用来封装需要监听在TCP端口的设备的所需要的服务端组件
 */
public abstract class ServerComponent implements FrameworkComponent, InitializingBean {

    private DeviceManager deviceManager;
    private IotSocketServer iotSocketServer;
    private IotProtocolFactory protocolFactory;
    private ProtocolTimeoutStorage protocolTimeoutManager;

    /**
     * 创建设备服务端
     * @return
     */
    public final IotSocketServer deviceServer() {
        if(this.iotSocketServer != null)
            return this.iotSocketServer;

        this.iotSocketServer = createDeviceServer();
        if(this.iotSocketServer == null)
            throw new IllegalStateException("未指定设备服务端对象: " + IotSocketServer.class.getName() + "在设备组件对象中: " + getClass().getSimpleName());

        return iotSocketServer;
    }

    protected abstract IotSocketServer createDeviceServer();

    public DeviceManager getDeviceManager() {
        return this.deviceManager;
    }

    /**
     * 创建协议工厂
     * @return
     */
    public final IotProtocolFactory protocolFactory() {
        if(this.protocolFactory != null) {
            return this.protocolFactory;
        }

        this.protocolFactory = createProtocolFactory();
        if(this.protocolFactory == null) {
            throw new BeanInitializationException("组件["+getClass().getSimpleName()+"]未创建协议工厂实例["+ProtocolFactory.class.getSimpleName()+"]");
        }

        if(this.protocolFactory instanceof ProtocolFactory) {
            ProtocolFactory protocolFactory = (ProtocolFactory) this.protocolFactory;
            if (protocolFactory.getDelegation() == null) {
                protocolFactory.setDelegation(protocolTimeoutStorage());
            }
        }

        return this.protocolFactory;
    }

    protected abstract IotProtocolFactory createProtocolFactory();

    /**
     * 设备服务端使用的报文类
     * 此类将用来标识唯一的设备服务组件
     * @return
     */
    public abstract Class<? extends SocketMessage> getMessageClass();

    public final ProtocolTimeoutStorage protocolTimeoutStorage() {
        if(protocolTimeoutManager != null) {
            return this.protocolTimeoutManager;
        }

        return this.protocolTimeoutManager = doCreateProtocolTimeoutStorage();
    }

    /**
     * 创建超时管理器
     * @return
     */
    protected ProtocolTimeoutStorage doCreateProtocolTimeoutStorage() {
        return new ProtocolTimeoutStorage(getName());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        deviceServer();
        protocolFactory();
        this.deviceManager = new DevicePipelineManager(getName(), null);
    }

}
